<!--
如果不指定服务端渲染接口，默认使用本地渲染
-->
<template>
    <Editor
        :mode="props.mode"
        :previewDebounce="props.previewDebounce"
        :placeholder="props.placeholder"
        :editorConfig="props.editorConfig"
        :locale="props.locale"
        :maxLength="props.maxLength"
        :plugins="plugins"
        :sanitize="props.sanitize"
        :remarkRehype="props.remarkRehype"
        :value="content"
        @change="handleChange"
        :uploadImages="props.uploadImages"
        class="bytemd-container"
    />
</template>

<script setup lang="ts">
import {Editor} from '@bytemd/vue-next'
import "bytemd/dist/index.css"
import "juejin-markdown-themes/dist/juejin.min.css"
//语法高亮的样式
import 'highlight.js/styles/default.css'
import byteMdZhHans from "bytemd/locales/zh_Hans.json";
import {computed} from "vue";
import stores from "/@/stores";
import {storeToRefs} from "pinia";
import {BytemdPlugin} from "bytemd";
import {Schema} from "hast-util-sanitize";
import {Options} from "remark-rehype";
import ssrPlugin from "/@/components/editor/SsrPlugin";
import highlightPlugin from "/@/components/editor/HighlightPlugin";
import mathPlugin from "/@/components/editor/MathPlugin";
import {MarkdownRenderFunction} from "/@/types/bytemd";
import mermaidPlugin from "/@/components/editor/MermaidPlugin";
import {fileApi} from "/@/api/file";

const emit = defineEmits<{
    (e: 'update:modelValue', value: string): void
}>()

interface Props {
    render?: MarkdownRenderFunction;//自定义markdown渲染，可以通过远程接口进行渲染
    modelValue?: string;//初始内容
    width?: string;
    height?: string;
    plugins?: Array<BytemdPlugin>;
    sanitize?: (schema: Schema) => Schema;
    remarkRehype?: Options;
    mode?: "split" | "tab" | "auto";//显示模式
    locale?: any;
    previewDebounce?: number;//预览的去抖动时间，毫秒
    placeholder?: string;//占位提示
    editorConfig?: Omit<any, 'value' | 'placeholder'>;//https://codemirror.net/5/doc/manual.html#config
    maxLength?: number;//限制最大长度，字符数
    uploadImages?: (files: File[]) => Promise<Pick<any, 'url' | 'alt' | 'title'>[]>;
}

const props = withDefaults(defineProps<Props>(), {
    mode: "auto",
    modelValue: "",
    locale: byteMdZhHans,
    plugins: () => [],
    previewDebounce: 300,
    placeholder: "在这里编辑内容",
    maxLength: 100000,
    uploadImages: (files: File[]) => {
        stores.commonStoreState.openLoading();
        try {
            return Promise.all(
                files.map(async (file) => {
                    const fileVo = await fileApi.uploadFile({
                        file: file
                    })
                    return {
                        title: fileVo.name,
                        alt: fileVo.name,
                        url: fileVo.url,
                    }
                })
            );
        } finally {
            stores.commonStoreState.closeLoading();
        }
    }
});
const plugins = computed(() => {
    if (props.render) {
        return [
            ssrPlugin(props.render, [
                highlightPlugin(),
                mathPlugin(),
                mermaidPlugin()
            ]),
        ]
    } else {
        return props.plugins
    }
});
const content = computed(() => {
    return props.modelValue
})

//markdown双向绑定
const handleChange = (markdown: string) => {
    emit("update:modelValue", markdown)
}

const width = computed(() => {
    return props.width || "100%";
})
const {screenWidth} = storeToRefs(stores.commonStoreState)
const height = computed(() => {
    if (props.height) {
        return props.height;
    }
    if (screenWidth.value < 768) {
        return "calc(100vh - 400px)";
    } else if (screenWidth.value < 992) {
        return "calc(100vh - 350px)";
    } else if (screenWidth.value < 1200) {
        return "calc(100vh - 320px)";
    } else {
        return "calc(100vh - 320px)";
    }
    // if (screenWidth.value < 768) {
    //     return "300px";
    // } else if (screenWidth.value < 992) {
    //     return "400px";
    // } else if (screenWidth.value < 1200) {
    //     return "450px";
    // } else {
    //     return "550px";
    // }
})
</script>

<style scoped lang="scss">
.bytemd-container {
    width: v-bind(width);

    :deep(.bytemd) {
        line-height: normal; /*去除el-form-item的行高带来的影响*/
        height: v-bind(height);
    }
}
</style>